/**
 * @fileoverview
 *   implementation of permament storage on client (browser)
 *   only option available in this version is localStorage mechanism
 * 
 * @author Sebastian Brzuzek sebastian@brzuzek.pl
 */

goog.provide('uxperf.Storage');

goog.require('uxperf.Config');
goog.require('goog.storage.mechanism.HTML5LocalStorage');
goog.require('goog.storage.mechanism.PrefixedMechanism');
goog.require('goog.array');

/**
 * Storage implementation
 *
 * @extends {goog.storage.mechanism.PrefixedMechanism}
 * @constructor
 */
uxperf.Storage = function () {
	var tmp = {};
	tmp[uxperf.Storage.CONFIG.KEY] = uxperf.Storage.DEFAULT_CONFIG;
	uxperf.Config.setDefaults(tmp);
  
  var strg_class = uxperf.Storage.STORAGE_CLASSES[uxperf.Storage.getParam(uxperf.Storage.CONFIG.TYPE)] || null;
  var strg = strg_class ? new strg_class() : null;
  if (!strg) {
    //TODO implement cookie storage as falback mechanism
    throw Error('HTML5 local storage support required');
  }
  
  /**
   * @type {string}
   */
  this.prefix_ = /** @type {string} */ uxperf.Storage.getParam(uxperf.Storage.CONFIG.PREFIX);
  
  goog.base(this, strg, this.prefix_);
  
  /**
   * storage identifier generated only if not available
   * @type {string}
   */
  this.storageId_ = this.get(uxperf.Storage.STORAGE_ID_KEY) ||
                    (this.prefix_ + goog.now() + '.' + Math.floor(Math.random() * 2147483648).toString(36));
};
goog.inherits(uxperf.Storage, goog.storage.mechanism.PrefixedMechanism);
goog.addSingletonGetter(uxperf.Storage);

/**
 * get storage prefix
 * @return {string}
 */
uxperf.Storage.getPrefix = function () {
  return uxperf.Storage.getInstance().prefix_;
};

/**
 * get storage id
 * @return {string}
 */
uxperf.Storage.getStorageId = function () {
  return uxperf.Storage.getInstance().storageId_;
};

/**
 * @inheritDoc
 */
uxperf.Storage.prototype.clear = function () {
  uxperf.Storage.superClass_.clear.call(this);
  //restore storageId
  this.set(uxperf.Storage.STORAGE_ID_KEY, this.storageId_);
};

/**
 * Total cleanup all information in storage
 */
uxperf.Storage.cleanup = function () {
  uxperf.Storage.superClass_.clear.call(uxperf.Storage.getInstance());
};

/**
 * Returns storage parameter value from current configuration
 *
 * @param {...(string|number|!Array.<number|string>)} var_args A number of keys
 *     (as strings, or nubmers, for array-like objects) to retrieve specific value
 *     from configuration structure. Can also be specified as a single array of keys.
 * @return {*} The resulting value. If, at any point, the value for a key
 *     is undefined, returns undefined.
 */
uxperf.Storage.getParam = function(var_args) {
	return uxperf.Config.getSub(uxperf.Storage.CONFIG.KEY, goog.array.toArray(arguments));
};

/**
 * constants related to configuration structure
 * @enum {string}
 */
uxperf.Storage.CONFIG = {
	KEY : 'storage',
	PREFIX : 'prefix',
	TYPE : 'type'
};

/**
 * storage types
 * 
 * @enum {Object}
 */
uxperf.Storage.STORAGE_CLASSES = {
  //'cookie' : cookieStorage
  //'session' : sessionStorage
  'local' : goog.storage.mechanism.HTML5LocalStorage
};

/**
 * Default configuration
 * @type {!Object}
 */
uxperf.Storage.DEFAULT_CONFIG = {};
uxperf.Storage.DEFAULT_CONFIG[uxperf.Storage.CONFIG.PREFIX] = 'uxperf';
uxperf.Storage.DEFAULT_CONFIG[uxperf.Storage.CONFIG.TYPE] = 'local';

/** @const storage id key */
uxperf.Storage.STORAGE_ID_KEY = 'storageID';
